using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.ServiceProcess;
using System.Threading;
using System.Drawing.Drawing2D;
using Microsoft.Office.Project.EPMSync.Service.Monitor.Properties;
using Microsoft.Office.Project.EPMSync.Config.Library;
using System.Globalization;

namespace Microsoft.Office.Project.EPMSync.Service.Monitor
{
    public partial class ServiceControl : UserControl
    {
        private string _serviceName;
        private string _customButtonName;
        private int _customButtonValue;
        private ServiceController _serviceController;
        private ManualResetEvent _pause = new ManualResetEvent(false);
        Thread _workerThread;

        delegate void SetButtonStateCallback();
        delegate void SetStatusCallback();

        LinearGradientBrush _redBrush;
        LinearGradientBrush _greenBrush;
        LinearGradientBrush _yellowBrush;
        LinearGradientBrush _greyBrush;
        
        Color _trimColor = Color.Red;
        private int _coloredBorderWidth = 6;

        public ServiceControl()
        {
            InitializeComponent();

            _redBrush = new LinearGradientBrush(
                new Rectangle(0, 0, this.Size.Width, this.Size.Height),
                Color.Red,
                Color.MistyRose,
                LinearGradientMode.Vertical);

            _greenBrush = new LinearGradientBrush(
                new Rectangle(0, 0, this.Size.Width, this.Size.Height),
                Color.Green,
                Color.LightGreen,
                LinearGradientMode.Vertical);

            _yellowBrush = new LinearGradientBrush(
                new Rectangle(0, 0, this.Size.Width, this.Size.Height),
                Color.Yellow,
                Color.LightYellow,
                LinearGradientMode.Vertical);

            _greyBrush = new LinearGradientBrush(
                new Rectangle(0, 0, this.Size.Width, this.Size.Height),
                Color.Gray,
                Color.LightGray,
                LinearGradientMode.Vertical);
        }

        public void StartServiceControl(string serviceName)
        {
            StartServiceControl(serviceName, String.Empty, 0);
        }

        public void StartServiceControl(string serviceName, string customButtonName, int customButtonValue)
        {
            _serviceName = serviceName;
            _customButtonName = customButtonName;
            _customButtonValue = customButtonValue;

            if (!String.IsNullOrEmpty(customButtonName))
            {
                buttonCustom.Text = _customButtonName;
                buttonCustom.Show();
            }
            else
                buttonCustom.Hide();
            
            // Create the service controller
            try
            {
                _serviceController = new ServiceController(_serviceName);
                textBoxServiceName.Text = _serviceController.DisplayName;
            }
            catch (ArgumentException)
            {
                _serviceController = null;
                textBoxServiceName.Text = _serviceName;
                labelStatus.Text = Resources.ErrorFindingService;
                _trimColor = Color.Red;
                //labelStatus.BackColor = Color.Red;
                buttonStart.Enabled = false;
                buttonStop.Enabled = false;
                buttonSuspend.Enabled = false;
                buttonResume.Enabled = false;
                buttonCustom.Enabled = false;

            }

            // Spawn thread to get updates on the control
            _workerThread = new Thread(new ThreadStart(UpdateMethod));
            _workerThread.Start();
            _pause.Set();
        }

        public void StopServiceControl()
        {
            _pause.Reset();
            Thread.Sleep(200);
            if (_workerThread != null)
                _workerThread.Abort();
            _pause.Set();
            _greenBrush.Dispose();
            _greyBrush.Dispose();
            _yellowBrush.Dispose();
            _redBrush.Dispose();
        }


        private void SetButtonState()
        {
            if (this.buttonCustom.InvokeRequired)
            {
                SetButtonStateCallback d = new SetButtonStateCallback(SetButtonState);
                this.Invoke(d, new object[] {});
            }
            else
            {
                if (_serviceController != null)
                {
                    // If it's stopped, we should be able to start it
                    buttonStart.Enabled = (_serviceController.Status == ServiceControllerStatus.Stopped);
                    // Check if we're allowed to try and stop it and make sure it's not already stopped.
                    buttonStop.Enabled = (_serviceController.CanStop && (_serviceController.Status != ServiceControllerStatus.Stopped));
                    // Check if we're allowed to pause it and see if it is not paused already.
                    buttonSuspend.Enabled = (_serviceController.CanPauseAndContinue && (_serviceController.Status != ServiceControllerStatus.Paused));
                    // If it's paused, we must be able to resume it.
                    buttonResume.Enabled = (_serviceController.Status == ServiceControllerStatus.Paused);
                    buttonCustom.Enabled = (_serviceController.Status == ServiceControllerStatus.Running);
                }
            }

        }

        public ServiceControllerStatus Status
        {
            get
            {
                if (_serviceController != null)
                    return _serviceController.Status;
                else
                    return ServiceControllerStatus.Stopped;
            }
        }

        private void SetStatus()
        {
            if (this.labelStatus.InvokeRequired)
            {
                SetStatusCallback d = new SetStatusCallback(SetStatus);
                this.Invoke(d, new object[] { });
            }
            else
            {
                if (_serviceController != null)
                {
                    if (this.labelStatus.Text != _serviceController.Status.ToString())
                    {
                        this.labelStatus.Text = _serviceController.Status.ToString();
                        if (_serviceController.Status == ServiceControllerStatus.Stopped)
                            _trimColor = Color.Red;
                        else if (_serviceController.Status == ServiceControllerStatus.Running)
                            _trimColor = Color.LightGreen;
                        else
                            _trimColor = Color.Yellow;
                        this.Invalidate();
                    }
                }
            }
        }

        public void UpdateServiceState()
        {
            if (_serviceController != null)
            {
                _serviceController.Refresh();
                SetButtonState();
                SetStatus();
            }
        }

        private void UpdateMethod()
        {
            int wakeupInterval = 500;
            DateTime wakeupTime = DateTime.Now.AddMilliseconds(wakeupInterval);

            try
            {
                do
                {
                    if (_serviceController != null)
                    {
                        if (DateTime.Now > wakeupTime)
                        {
                            UpdateServiceState();
                            wakeupTime = DateTime.Now.AddMilliseconds(wakeupInterval);
                        }

                        // Wait before cycling.
                        Thread.Sleep(100);
                    }
                    else
                        Thread.Sleep(1000);

                    // Block if the service is paused or is shutting down.
                    _pause.WaitOne();
                } while (true);
            }
            catch (ThreadAbortException)
            {
                Thread.ResetAbort();
            }
        }


        #region Event Handlers

        private void buttonStart_Click(object sender, EventArgs e)
        {
            try
            {
                _serviceController.Start();
            }
            catch (Win32Exception ex)
            {
                RightAwareMessageBox.Show(String.Format(CultureInfo.InvariantCulture, Resources.Win32Exception, ex.Message),
                    Resources.MonitorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (InvalidOperationException ex)
            {
                RightAwareMessageBox.Show(String.Format(CultureInfo.InvariantCulture, Resources.ServiceException, ex.Message),
                    Resources.MonitorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void buttonStop_Click(object sender, EventArgs e)
        {
            try
            {
                _serviceController.Stop();
            }
            catch (Win32Exception ex)
            {
                RightAwareMessageBox.Show(String.Format(CultureInfo.InvariantCulture, Resources.Win32Exception, ex.Message),
                    Resources.MonitorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (InvalidOperationException ex)
            {
                RightAwareMessageBox.Show(String.Format(CultureInfo.InvariantCulture, Resources.ServiceException, ex.Message),
                    Resources.MonitorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void buttonSuspend_Click(object sender, EventArgs e)
        {
            try
            {
                _serviceController.Pause();
            }
            catch (Win32Exception ex)
            {
                RightAwareMessageBox.Show(String.Format(CultureInfo.InvariantCulture, Resources.Win32Exception, ex.Message),
                    Resources.MonitorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (InvalidOperationException ex)
            {
                RightAwareMessageBox.Show(String.Format(CultureInfo.InvariantCulture, Resources.ServiceException, ex.Message),
                    Resources.MonitorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void buttonResume_Click(object sender, EventArgs e)
        {
            try
            {
                _serviceController.Continue();
            }
            catch (Win32Exception ex)
            {
                RightAwareMessageBox.Show(String.Format(CultureInfo.InvariantCulture, Resources.Win32Exception, ex.Message),
                    Resources.MonitorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (InvalidOperationException ex)
            {
                RightAwareMessageBox.Show(String.Format(CultureInfo.InvariantCulture, Resources.ServiceException, ex.Message),
                    Resources.MonitorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void buttonCustom_Click(object sender, EventArgs e)
        {
            try
            {
                _serviceController.ExecuteCommand(_customButtonValue);
            }
            catch (Win32Exception ex)
            {
                RightAwareMessageBox.Show(String.Format(CultureInfo.InvariantCulture, Resources.Win32Exception, ex.Message),
                    Resources.MonitorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (InvalidOperationException ex)
            {
                RightAwareMessageBox.Show(String.Format(CultureInfo.InvariantCulture, Resources.ServiceException, ex.Message),
                    Resources.MonitorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void ServiceContol_Paint(object sender, PaintEventArgs e)
        {
            Pen trimPen = null;

            if (_trimColor == Color.Red)
                trimPen = new Pen(_redBrush);
            else if (_trimColor == Color.LightGreen)
                trimPen = new Pen(_greenBrush);
            else if (_trimColor == Color.Yellow)
                trimPen = new Pen(_yellowBrush);
            else
                trimPen = new Pen(_greyBrush);

            trimPen.Width = Convert.ToSingle(_coloredBorderWidth);
            int offset = 2 + (_coloredBorderWidth / 2);

            trimPen.LineJoin = System.Drawing.Drawing2D.LineJoin.Round;

            Rectangle rectangle1 = new Rectangle(offset, offset, this.Size.Width - (offset * 2), this.Size.Height - (offset * 2));
            e.Graphics.DrawRectangle(trimPen, rectangle1);
            e.Graphics.DrawRectangle(Pens.Black, 2, 2, this.Size.Width - 4, this.Size.Height - 4);
            e.Graphics.DrawRectangle(Pens.Black, 2 + _coloredBorderWidth, 2 + _coloredBorderWidth, this.Size.Width - 4 - (2 * _coloredBorderWidth), 
                this.Size.Height - 4 - (2 * _coloredBorderWidth));

            //Dispose of the pen.
            trimPen.Dispose();

        }

        #endregion

    }
}
